#include "../../config.h"

#include <glibmm/i18n.h>

#include "element.h"
#include "../log.h"

namespace gpyp {
namespace conf {

void Element::on_preload() {
  loaded_ = false;
  for(ElementList::iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    (*iter)->on_preload();
  }
}
void Element::on_load(ConfParser  &/*parser*/,
                      const char  */*element_name*/,
                      const char **attribute_names,
                      const char **attribute_values) {
  loaded_        = true;
  element_depth_ = 0;

  const char **name, **value;
  for(name = attribute_names, value = attribute_values;
      *name && *value; ++name, ++value) {
    for(AttributeList::iterator iter = attributes_.begin();
        iter != attributes_.end(); ++iter) {
      if ((*iter)->get_name() == *name) {
        (*iter)->on_load(*value);
        break;
      }
    }
  }
}
void Element::on_start_element(ConfParser  &parser,
                               const char  *element_name,
                               const char **attribute_names,
                               const char **attribute_values,
                               GError     **/*error*/) {
  if (element_depth_ == 0) {
    for(ElementList::iterator iter = elements_.begin();
        iter != elements_.end(); ++iter) {
      if (!(*iter)->loaded_ &&
          (*iter)->get_name() == element_name) {
        parser.push(iter->get(), element_name,
                    attribute_names, attribute_values);
        return;
      }
    }
  }
  ++element_depth_;
}
void Element::on_end_element(ConfParser &parser,
                             const char */*element_name*/,
                             GError    **/*error*/) {
  if (element_depth_ == 0) {
    parser.pop();
    return;
  }
  --element_depth_;
}
void Element::on_postload() {
  if (!loaded_) {
    on_load_default();
    on_default_loaded();
  }
  for(ElementList::iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    (*iter)->on_postload();
  }
}
void Element::on_load_default() {
}
void Element::on_default_loaded() {
}

void Element::on_presave() {
  for(ElementList::iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    (*iter)->on_presave();
  }
  signal_presave_();
}
void Element::on_save(Writer &writer, bool force) {
  writer.indent();
  writer.write("<");
  writer.write(get_name(), true);
  on_save_attributes(writer, force);
  if (on_get_has_contents(force)) {
    writer.write(">");
    writer.new_line();
    writer.push();
    on_save_contents(writer, force);
    writer.pop();
    writer.indent();
    writer.write("</");
    writer.write(get_name(), true);
    writer.write(">");
  } else {
    writer.write("/>");
  }
}
void Element::on_save_attributes(Writer &writer, bool force) {
  for(AttributeList::iterator iter = attributes_.begin();
      iter != attributes_.end(); ++iter) {
    if (force || (*iter)->get_dirty()) {
      writer.write(" ");
      (*iter)->on_save(writer);
    }
  }
}
void Element::on_save_contents(Writer &writer, bool force) {
  for(ElementList::iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    if (force || (*iter)->get_dirty()) {
      (*iter)->on_save(writer, force);
      writer.new_line();
    }
  }
}
bool Element::on_get_has_contents(bool force) const {
  if (force && elements_.size()) return true;
  for(ElementList::const_iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    if ((*iter)->get_dirty()) return true;
  }
  return false;
}

bool Element::on_get_dirty() const {
  for(AttributeList::const_iterator iter = attributes_.begin();
      iter != attributes_.end(); ++iter) {
    if ((*iter)->get_dirty()) return true;
  }
  for(ElementList::const_iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    if ((*iter)->get_dirty()) return true;
  }
  return false;
}
void Element::on_set_dirty(bool dirty) {
  for(AttributeList::iterator iter = attributes_.begin();
      iter != attributes_.end(); ++iter) {
    (*iter)->set_dirty(dirty);
  }
  for(ElementList::iterator iter = elements_.begin();
      iter != elements_.end(); ++iter) {
    (*iter)->set_dirty(dirty);
  }
}

void Element::add_element(RefElement element) {
  ElementList::iterator iter =
    std::find(elements_.begin(), elements_.end(), element);
  if (iter == elements_.end()) {
    elements_.push_back(element);
  } else {
    log::dbg << "bug: Element::add_element" << log::endl;
  }
}
void Element::add_attribute(RefAttributeBase attribute) {
  AttributeList::iterator iter =
    std::find(attributes_.begin(), attributes_.end(), attribute);
  if (iter == attributes_.end()) {
    attributes_.push_back(attribute);
  } else {
    log::dbg << "bug: Element::add_attribute" << log::endl;
  }
}

void Element::remove_element(RefElement element) {
  ElementList::iterator iter =
    std::find(elements_.begin(), elements_.end(), element);
  if (iter != elements_.end()) {
    elements_.erase(iter);
  } else {
    log::dbg << "bug: Element::remove_element" << log::endl;
  }
}
void Element::remove_attribute(RefAttributeBase attribute) {
  AttributeList::iterator iter =
    std::find(attributes_.begin(), attributes_.end(), attribute);
  if (iter != attributes_.end()) {
    attributes_.erase(iter);
  } else {
    log::dbg << "bug: Element::remove_attribute" << log::endl;
  }
}

Element::Element(const Glib::ustring &name) :
  Node          (name),
  loaded_       (true),
  element_depth_(0)
{
}

}/*conf*/
}/*gpyp*/
